home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / socket.old < prev    next >
Text File  |  1992-03-15  |  47KB  |  1,983 lines

  1. /* Application programming interface routines - based loosely on the
  2.  * "socket" model in Berkeley UNIX.
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  */
  6. #include <stdio.h>
  7. #include <time.h>
  8. #include <errno.h>
  9. #ifdef    __STDC__
  10. #include <stdarg.h>
  11. #endif
  12. #include "global.h"
  13. #include "mbuf.h"
  14. #include "netuser.h"
  15. #include "timer.h"
  16. #include "iface.h"
  17. #include "ip.h"
  18. #include "tcp.h"
  19. #include "udp.h"
  20. #include "ax25.h"
  21. #include "lapb.h"
  22. #include "netrom.h"
  23. #include "nr4.h"
  24. #include "proc.h"
  25. #include "lzw.h"
  26. #include "usock.h"
  27. #include "socket.h"
  28. #include "config.h"
  29.  
  30. static void autobind __ARGS((int s,int af));
  31. static int checkaddr __ARGS((int type,char *name,int namelen));
  32. static void rip_recv __ARGS((struct raw_ip *rp));
  33. static void s_trcall __ARGS((struct tcb *tcb,int cnt));
  34. static void s_tscall __ARGS((struct tcb *tcb,int old,int new));
  35. static void s_ttcall __ARGS((struct tcb *tcb,int cnt));
  36. static void s_urcall __ARGS((struct iface *iface,struct udp_cb *udp,int cnt));
  37. static void trdiscard __ARGS((struct tcb *tcb,int cnt));
  38. #ifdef    NETROM
  39. static void s_nrcall __ARGS((struct nr4cb *cb,int16 cnt));
  40. static void s_nscall __ARGS((struct nr4cb *cb,int old,int new));
  41. static void s_ntcall __ARGS((struct nr4cb *cb,int16 cnt));
  42. #endif
  43.  
  44. static int16 Lport = 1024;
  45.  
  46. char *Socktypes[] = {
  47.     "Not Used",
  48.     "TCP",
  49.     "UDP",
  50.     "AX25 I",
  51.     "AX25 UI",
  52.     "Raw IP",
  53.     "NETROM3",
  54.     "NETROM",
  55.     "Loc St",
  56.     "Loc Dg"
  57. };
  58. char Badsocket[] = "Bad socket";
  59. struct usock *Usock;        /* Socket entry array */
  60. int Nusock = DEFNSOCK;        /* Number of socket entries */
  61.  
  62. /* The following two variables are needed because there can be only one
  63.  * socket listening on each of the AX.25 modes (I and UI)
  64.  */
  65. #ifdef    AX25
  66. int Axi_sock = -1;    /* Socket number listening for AX25 connections */
  67. static int Axui_sock = -1;    /* Socket number listening for AX25 UI frames */
  68. static struct mbuf *Bcq;    /* Queue of incoming UI frames */
  69.  
  70. /* Function that handles incoming UI frames from lapb.c */
  71. void
  72. beac_input(iface,src,bp)
  73. struct iface *iface;
  74. char *src;
  75. struct mbuf *bp;
  76. {
  77.     struct mbuf *hdr;
  78.     struct sockaddr_ax *sax;
  79.  
  80.     if(Axui_sock == -1){
  81.         /* Nobody there to read it */
  82.         free_p(bp);
  83.     } else {
  84.         if((hdr = pushdown(NULLBUF,sizeof(struct sockaddr_ax))) == NULLBUF){
  85.             free_p(bp);
  86.             return;
  87.         }
  88.         sax = (struct sockaddr_ax *)hdr->data;
  89.         sax->sax_family = AF_AX25;
  90.         memcpy(sax->ax25_addr,src,AXALEN);
  91.         strncpy(sax->iface,iface->name,ILEN);
  92.         hdr->next = bp;
  93.         enqueue(&Bcq,hdr);
  94.     }
  95. }
  96. #endif
  97.  
  98. /* Initialize user socket array */
  99. void
  100. sockinit()
  101. {
  102.     if(Usock != NULLUSOCK)
  103.         return;    /* Already initialized */
  104.     Usock = (struct usock *)callocw(Nusock,sizeof(struct usock));
  105. }
  106.  
  107. /* Create a user socket, return socket index
  108.  * The mapping to actual protocols is as follows:
  109.  *        
  110.  *        
  111.  * ADDRESS FAMILY    Stream        Datagram    Raw        Seq. Packet
  112.  *
  113.  * AF_INET        TCP        UDP        IP
  114.  * AF_AX25        I-frames    UI-frames
  115.  * AF_NETROM                        NET/ROM L3  NET/ROM L4
  116.  * AF_LOCAL        stream loopback    packet loopback
  117.  */
  118. int
  119. socket(af,type,protocol)
  120. int af;        /* Address family */
  121. int type;    /* Stream or datagram */
  122. int protocol;    /* Used for raw IP sockets */
  123. {
  124.     register struct usock *up;
  125.     int s;
  126.  
  127.     for(up=Usock;up < &Usock[Nusock];up++)
  128.         if(up->type == NOTUSED)
  129.             break;
  130.  
  131.     if(up == &Usock[Nusock]){
  132.         /* None left */
  133.         errno = EMFILE;
  134.         return -1;
  135.     }
  136.     up->refcnt = 1;
  137.     s = up - Usock + SOCKBASE;
  138.     errno = 0;
  139.     up->noblock = 0;
  140.     up->rdysock = -1;
  141.     up->cb.p = NULLCHAR;
  142.     up->peername = up->name = NULLCHAR;
  143.     up->namelen = up->peernamelen = 0;
  144.     up->owner = Curproc;
  145.     up->obuf = NULLBUF;
  146.     memset(up->errcodes,0,sizeof(up->errcodes));
  147.     memset(up->eol,0,sizeof(up->eol));
  148.     up->flush = '\n';    /* default is line buffered */
  149.     switch(af){
  150.     case AF_LOCAL:
  151.         up->cb.local = (struct loc *) callocw(1,sizeof(struct loc));
  152.         up->cb.local->peer = up;    /* connect to self */
  153.         switch(type){
  154.         case SOCK_STREAM:
  155.             up->type = TYPE_LOCAL_STREAM;
  156.             up->cb.local->hiwat = LOCSFLOW;
  157.             break;
  158.         case SOCK_DGRAM:
  159.             up->type = TYPE_LOCAL_DGRAM;
  160.             up->cb.local->hiwat = LOCDFLOW;
  161.             break;
  162.         default:
  163.             free(up->cb.local);
  164.             errno = ESOCKTNOSUPPORT;
  165.             break;
  166.         }
  167.         break;
  168. #ifdef    AX25
  169.     case AF_AX25:
  170.         switch(type){
  171.         case SOCK_STREAM:
  172.             up->type = TYPE_AX25I;
  173.             break;
  174.         case SOCK_DGRAM:
  175.             up->type = TYPE_AX25UI;
  176.             break;
  177.         default:
  178.             errno = ESOCKTNOSUPPORT;
  179.             break;
  180.         }
  181.         strcpy(up->eol,AX_EOL);
  182.         break;
  183. #endif
  184. #ifdef NETROM
  185.     case AF_NETROM:
  186.         switch(type){
  187.         case SOCK_RAW:
  188.             up->type = TYPE_NETROML3;
  189.             up->cb.rnr = raw_nr((char)protocol);
  190.             break;
  191.         case SOCK_SEQPACKET:
  192.             up->type = TYPE_NETROML4;
  193.             break;
  194.         default:
  195.             errno = ESOCKTNOSUPPORT;
  196.             break;
  197.         }
  198.         strcpy(up->eol,AX_EOL);
  199.         break;
  200. #endif
  201.     case AF_INET:
  202.         switch(type){
  203.         case SOCK_STREAM:
  204.             up->type = TYPE_TCP;
  205.             strcpy(up->eol,INET_EOL);
  206.             break;
  207.         case SOCK_DGRAM:
  208.             up->type = TYPE_UDP;
  209.             break;
  210.         case SOCK_RAW:
  211.             up->type = TYPE_RAW;
  212.             up->cb.rip = raw_ip(protocol,rip_recv);
  213.                         up->cb.rip->user = s;
  214.             break;
  215.         default:
  216.             errno = ESOCKTNOSUPPORT;
  217.             break;
  218.         }
  219.         break;
  220.     default:
  221.         errno = EAFNOSUPPORT;
  222.         break;
  223.     }
  224.     if(errno)
  225.         return -1;
  226.  
  227.     return s;
  228. }
  229.  
  230. /* Attach a local address/port to a socket. If not issued before a connect
  231.  * or listen, will be issued automatically
  232.  */
  233. int
  234. bind(s,name,namelen)
  235. int s;        /* Socket index */
  236. char *name;    /* Local name */
  237. int namelen;    /* Length of name */
  238. {
  239.     register struct usock *up;
  240.     union sp local;
  241.     struct socket lsock;
  242.  
  243.     if((up = itop(s)) == NULLUSOCK){
  244.         errno = EBADF;
  245.         return -1;
  246.     }
  247.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  248.         errno = EINVAL;
  249.         return -1;
  250.     }
  251.     if(name == NULLCHAR){
  252.         errno = EFAULT;
  253.         return -1;
  254.     }
  255.     if(up->name != NULLCHAR){
  256.         /* Bind has already been issued */
  257.         errno = EINVAL;
  258.         return -1;
  259.     }
  260.     if(checkaddr(up->type,name,namelen) == -1){
  261.         /* Incorrect length or family for chosen protocol */
  262.         errno = EAFNOSUPPORT;
  263.         return -1;    
  264.     }
  265.     /* Stash name in an allocated block */
  266.     up->namelen = namelen;
  267.     up->name = mallocw(namelen);
  268.     memcpy(up->name,name,namelen);
  269.     /* Create control block for datagram sockets */
  270.     switch(up->type){
  271.     case TYPE_UDP:
  272.         local.in = (struct sockaddr_in *)up->name;
  273.         lsock.address = local.in->sin_addr.s_addr;
  274.         lsock.port = local.in->sin_port;
  275.         up->cb.udp = open_udp(&lsock,s_urcall);
  276.         up->cb.udp->user = s;
  277.         break;
  278. #ifdef    AX25
  279.     case TYPE_AX25UI:
  280.         if(Axui_sock != -1){
  281.             errno = EADDRINUSE;
  282.             return -1;
  283.         }
  284.         Axui_sock = s;
  285.         break;
  286. #endif
  287.     }
  288.     return 0;
  289. }
  290. /* Post a listen on a socket */
  291. int
  292. listen(s,backlog)
  293. int s;        /* Socket index */
  294. int backlog;    /* 0 for a single connection, 1 for multiple connections */
  295. {
  296.     register struct usock *up;
  297.     union sp local;
  298.     struct socket lsock;
  299.  
  300.     if((up = itop(s)) == NULLUSOCK){
  301.         errno = EBADF;
  302.         return -1;
  303.     }
  304.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  305.         errno = EINVAL;
  306.         return -1;
  307.     }
  308.     if(up->cb.p != NULLCHAR){
  309.         errno = EISCONN;
  310.         return -1;
  311.     }
  312.     switch(up->type){
  313.     case TYPE_TCP:
  314.         if(up->name == NULLCHAR)
  315.             autobind(s,AF_INET);
  316.  
  317.         local.in = (struct sockaddr_in *)up->name;
  318.         lsock.address = local.in->sin_addr.s_addr;
  319.         lsock.port = local.in->sin_port;
  320.         up->cb.tcb = open_tcp(&lsock,NULLSOCK,
  321.          backlog ? TCP_SERVER:TCP_PASSIVE,0,
  322.         s_trcall,s_ttcall,s_tscall,0,s);
  323.         break;
  324. #ifdef AX25
  325.     case TYPE_AX25I:
  326.         if(up->name == NULLCHAR)
  327.             autobind(s,AF_AX25);
  328.         if(s != Axi_sock){
  329.             errno = EOPNOTSUPP;
  330.             return -1;
  331.         }
  332.         local.ax = (struct sockaddr_ax *)up->name;
  333.         up->cb.ax25 = open_ax25(NULLIF,local.ax->ax25_addr,NULLCHAR,
  334.          backlog ? AX_SERVER:AX_PASSIVE,0,
  335.          s_arcall,s_atcall,s_ascall,s);
  336.         break;
  337. #endif
  338. #ifdef NETROM
  339.     case TYPE_NETROML4:
  340.         if(up->name == NULLCHAR)
  341.             autobind(s,AF_NETROM);
  342.         local.nr = (struct sockaddr_nr *)up->name;
  343.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,NULLNRADDR,
  344.          backlog ? AX_SERVER:AX_PASSIVE,
  345.          s_nrcall,s_ntcall,s_nscall,s);
  346.         break;
  347. #endif
  348.     default:
  349.         /* Listen not supported on datagram sockets */
  350.         errno = EOPNOTSUPP;
  351.         return -1;        
  352.     }
  353.     return 0;
  354. }
  355. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  356. int
  357. connect(s,peername,peernamelen)
  358. int s;            /* Socket index */
  359. char *peername;        /* Peer name */
  360. int peernamelen;    /* Length of peer name */
  361. {
  362.     register struct usock *up;
  363.     union cb cb;
  364.     union sp local,remote;
  365.     struct socket lsock,fsock;
  366. #ifdef    AX25
  367.     struct iface *iface;
  368. #endif
  369.  
  370.     if((up = itop(s)) == NULLUSOCK){
  371.         errno = EBADF;
  372.         return -1;
  373.     }
  374.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  375.         errno = EINVAL;
  376.         return -1;
  377.     }
  378.     if(peername == NULLCHAR){
  379.         /* Connect must specify a remote address */
  380.         errno = EFAULT;
  381.         return -1;
  382.     }
  383.     if(checkaddr(up->type,peername,peernamelen) == -1){
  384.         errno = EAFNOSUPPORT;
  385.         return -1;
  386.     }
  387.     /* Raw socket control blocks are created in socket() */
  388.     if(up->type != TYPE_RAW && up->type != TYPE_NETROML3 &&
  389.        up->cb.p != NULLCHAR){
  390.         errno = EISCONN;
  391.         return -1;
  392.     }
  393.     up->peername = mallocw(peernamelen);
  394.     memcpy(up->peername,peername,peernamelen);
  395.     up->peernamelen = peernamelen;
  396.  
  397.     /* Set up the local socket structures */
  398.     if(up->name == NULLCHAR){
  399.         switch(up->type){
  400.         case TYPE_TCP:
  401.         case TYPE_UDP:
  402.         case TYPE_RAW:
  403.             autobind(s,AF_INET);
  404.             break;
  405. #ifdef    AX25
  406.         case TYPE_AX25I:
  407.         case TYPE_AX25UI:
  408.             autobind(s,AF_AX25);
  409.             break;
  410. #endif
  411. #ifdef    NETROM
  412.         case TYPE_NETROML3:
  413.         case TYPE_NETROML4:
  414.             autobind(s,AF_NETROM);
  415.             break;
  416. #endif
  417.         }
  418.     }
  419.     switch(up->type){
  420.     case TYPE_TCP:
  421.         /* Construct the TCP-style ports from the sockaddr structs */
  422.         local.in = (struct sockaddr_in *)up->name;
  423.         remote.in = (struct sockaddr_in *)up->peername;
  424.  
  425.         if(local.in->sin_addr.s_addr == INADDR_ANY)
  426.             /* Choose a local address */
  427.             local.in->sin_addr.s_addr =
  428.              locaddr(remote.in->sin_addr.s_addr);
  429.  
  430.         lsock.address = local.in->sin_addr.s_addr;
  431.         lsock.port = local.in->sin_port;
  432.         fsock.address = remote.in->sin_addr.s_addr;
  433.         fsock.port = remote.in->sin_port;
  434.  
  435.         /* Open the TCB in active mode */
  436.         up->cb.tcb = open_tcp(&lsock,&fsock,TCP_ACTIVE,0,
  437.          s_trcall,s_ttcall,s_tscall,0,s);
  438.  
  439.         /* Wait for the connection to complete */
  440.         while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != TCP_ESTABLISHED){
  441.             if(up->noblock){
  442.                 errno = EWOULDBLOCK;
  443.                 return -1;
  444.             } else if((errno = pwait(up)) != 0){
  445.                 return -1;
  446.             }
  447.         }
  448.         if(cb.tcb == NULLTCB){
  449.             /* Probably got refused */
  450.             free(up->peername);
  451.             up->peername = NULLCHAR;
  452.             errno = ECONNREFUSED;
  453.             return -1;
  454.         }
  455.         break;
  456.     case TYPE_UDP:
  457. #ifdef    AX25
  458.     case TYPE_AX25UI:
  459. #endif
  460. #ifdef    NETROM
  461.     case TYPE_NETROML3:
  462. #endif
  463.     case TYPE_RAW:
  464.         /* Control block already created by bind() */
  465.         break;
  466. #ifdef    AX25
  467.     case TYPE_AX25I:
  468.         local.ax = (struct sockaddr_ax *)up->name;
  469.         remote.ax = (struct sockaddr_ax *)up->peername;
  470.         if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  471.             errno = EINVAL;
  472.             return -1;
  473.         }
  474.         if(local.ax->ax25_addr[0] == '\0'){
  475.             /* The local address was unspecified; set it from
  476.              * the interface address
  477.              */
  478.             memcpy(local.ax->ax25_addr,iface->hwaddr,AXALEN);
  479.         }
  480.         /* If we already have an AX25 link we can use it */
  481.         if((up->cb.ax25 = find_ax25(local.ax->ax25_addr,
  482.                         remote.ax->ax25_addr)) != NULLAX25
  483.            && up->cb.ax25->state != LAPB_DISCONNECTED &&
  484.            up->cb.ax25->user == -1) {
  485.             up->cb.ax25->user = s;
  486.             up->cb.ax25->r_upcall = s_arcall;
  487.             up->cb.ax25->t_upcall = s_atcall;
  488.             up->cb.ax25->s_upcall = s_ascall;
  489.             if(up->cb.ax25->state == LAPB_CONNECTED
  490.                || up->cb.ax25->state == LAPB_RECOVERY)
  491.                     return 0;
  492.         } else
  493.             up->cb.ax25 = open_ax25(iface,local.ax->ax25_addr,
  494.              remote.ax->ax25_addr,AX_ACTIVE,
  495.              Axwindow,s_arcall,s_atcall,s_ascall,s);
  496.  
  497.         /* Wait for the connection to complete */
  498.         while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != LAPB_CONNECTED){
  499.             if(up->noblock){
  500.                 errno = EWOULDBLOCK;
  501.                 return -1;
  502.             } else if((errno = pwait(up)) != 0){
  503.                 return -1;
  504.             }
  505.         }
  506.         if(cb.ax25 == NULLAX25){
  507.             /* Connection probably already exists */
  508.             free(up->peername);
  509.             up->peername = NULLCHAR;
  510.             errno = ECONNREFUSED;
  511.             return -1;
  512.         }
  513.         break;
  514. #endif
  515. #ifdef    NETROM
  516.     case TYPE_NETROML4:
  517.         local.nr = (struct sockaddr_nr *)up->name;
  518.         remote.nr = (struct sockaddr_nr *)up->peername;
  519.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,&remote.nr->nr_addr,
  520.          AX_ACTIVE,s_nrcall,s_ntcall,s_nscall,s);
  521.  
  522.         /* Wait for the connection to complete */
  523.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB && cb.nr4->state != NR4STCON){
  524.             if(up->noblock){
  525.                 errno = EWOULDBLOCK;
  526.                 return -1;
  527.             } else if((errno = pwait(up)) != 0){
  528.                 return -1;
  529.             }
  530.         }
  531.         if(cb.nr4 == NULLNR4CB){
  532.             /* Connection probably already exists */
  533.             free(up->peername);
  534.             up->peername = NULLCHAR;
  535.             errno = ECONNREFUSED;
  536.             return -1;
  537.         }
  538.         break;
  539. #endif
  540.     }
  541.     return 0;
  542. }
  543. /* Wait for a connection. Valid only for connection-oriented sockets. */
  544. int
  545. accept(s,peername,peernamelen)
  546. int s;            /* Socket index */
  547. char *peername;        /* Peer name */
  548. int *peernamelen;    /* Length of peer name */
  549. {
  550.     int i;
  551.     register struct usock *up;
  552.  
  553.     if((up = itop(s)) == NULLUSOCK){
  554.         errno = EBADF;
  555.         return -1;
  556.     }
  557.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  558.         errno = EINVAL;
  559.         return -1;
  560.     }
  561.     if(up->cb.p == NULLCHAR){
  562.         errno = EOPNOTSUPP;
  563.         return -1;
  564.     }
  565.     /* Accept is valid only for stream sockets */
  566.     switch(up->type){
  567.     case TYPE_TCP:
  568. #ifdef    AX25
  569.     case TYPE_AX25I:
  570. #endif
  571. #ifdef    NETROM
  572.     case TYPE_NETROML4:
  573. #endif
  574.         break;
  575.     default:
  576.         errno = EOPNOTSUPP;
  577.         return -1;
  578.     }    
  579.     /* Wait for the state-change upcall routine to signal us */
  580.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  581.         if(up->noblock){
  582.             errno = EWOULDBLOCK;
  583.             return -1;
  584.         } else if((errno = pwait(up)) != 0){
  585.             return -1;
  586.         }
  587.     }
  588.     if(up->cb.p == NULLCHAR){
  589.         /* Blown away */
  590.         errno = EBADF;
  591.         return -1;
  592.     }
  593.     i = up->rdysock;
  594.     up->rdysock = -1;
  595.  
  596.     up = itop(i);
  597.     if(peername != NULLCHAR && peernamelen != NULL){
  598.         *peernamelen = min(up->peernamelen,*peernamelen);
  599.         memcpy(peername,up->peername,*peernamelen);
  600.     }
  601.     return i;
  602. }
  603. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  604.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  605.  * the len parameter.
  606.  */
  607. int
  608. recv_mbuf(s,bpp,flags,from,fromlen)
  609. int s;            /* Socket index */
  610. struct mbuf **bpp;    /* Place to stash receive buffer */
  611. int flags;        /* Unused; will control out-of-band data, etc */
  612. char *from;        /* Peer address (only for datagrams) */
  613. int *fromlen;        /* Length of peer address */
  614. {
  615.     register struct usock *up;
  616.     int cnt;
  617.     union cb cb;
  618.     struct socket fsocket;
  619. #ifdef    NETROM
  620.     struct nr3hdr n3hdr;
  621. #endif
  622.     union sp remote;
  623.     struct ip ip;
  624.     struct mbuf *bp;
  625.  
  626.     if((up = itop(s)) == NULLUSOCK){
  627.         errno = EBADF;
  628.         return -1;
  629.     }
  630.     if(up->ibuf != NULLBUF){
  631.         /* Return input buffer */
  632.         cnt = len_p(up->ibuf);
  633.         if(bpp != NULLBUFP)
  634.             *bpp = up->ibuf;
  635.         else
  636.             free_p(up->ibuf);
  637.         up->ibuf = NULLBUF;        
  638.         return cnt;
  639.     }
  640.     switch(up->type){
  641.     case TYPE_LOCAL_STREAM:
  642.     case TYPE_LOCAL_DGRAM:
  643.         while(up->cb.local != NULLLOC && up->cb.local->q == NULLBUF
  644.               && up->cb.local->peer != NULLUSOCK){
  645.             if(up->noblock){
  646.                 errno = EWOULDBLOCK;
  647.                 return -1;
  648.             } else if((errno = pwait(up)) != 0){
  649.                 return -1;
  650.             }
  651.         }
  652.         if(up->cb.local == NULLLOC){
  653.             errno = EBADF;
  654.             return -1;
  655.         }
  656.         if(up->cb.local->q == NULLBUF &&
  657.            up->cb.local->peer == NULLUSOCK){
  658.             errno = ENOTCONN;
  659.             return -1;
  660.         }
  661.         /* For datagram sockets, this will return the
  662.          * first packet on the queue. For stream sockets,
  663.          * this will return everything.
  664.          */
  665.         bp = dequeue(&up->cb.local->q);
  666.         if(up->cb.local->q == NULLBUF
  667.          && (up->cb.local->flags & LOC_SHUTDOWN))
  668.             close_s(s);
  669.         psignal(up,0);
  670.         cnt = len_p(bp);
  671.         break;
  672.     case TYPE_TCP:
  673.         while((cb.tcb = up->cb.tcb) != NULLTCB
  674.          && cb.tcb->r_upcall != trdiscard
  675.                  && (cnt = recv_tcp(cb.tcb,&bp,(int16)0)) == -1){
  676.             if(up->noblock){
  677.                 errno = EWOULDBLOCK;
  678.                 return -1;
  679.             } else if((errno = pwait(up)) != 0){
  680.                 return -1;
  681.             }
  682.         }
  683.         if(cb.tcb == NULLTCB){
  684.             /* Connection went away */
  685.             errno = ENOTCONN;
  686.             return -1;
  687.         } else if(cb.tcb->r_upcall == trdiscard){
  688.             /* Receive shutdown has been done */
  689.             errno = ENOTCONN;    /* CHANGE */
  690.             return -1;
  691.         }
  692.         break;
  693.     case TYPE_UDP:
  694.         while((cb.udp = up->cb.udp) != NULLUDP
  695.         && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  696.             if(up->noblock){
  697.                 errno = EWOULDBLOCK;
  698.                 return -1;
  699.             } else if((errno = pwait(up)) != 0){
  700.                 return -1;
  701.             }
  702.         }
  703.         if(cb.udp == NULLUDP){
  704.             /* Connection went away */
  705.             errno = ENOTCONN;
  706.             return -1;
  707.         }
  708.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  709.             remote.in = (struct sockaddr_in *)from;
  710.             remote.in->sin_family = AF_INET;
  711.             remote.in->sin_addr.s_addr = fsocket.address;
  712.             remote.in->sin_port = fsocket.port;
  713.             *fromlen = SOCKSIZE;
  714.         }
  715.         break;
  716.     case TYPE_RAW:
  717.         while((cb.rip = up->cb.rip) != NULLRIP
  718.          && cb.rip->rcvq == NULLBUF){
  719.             if(up->noblock){
  720.                 errno = EWOULDBLOCK;
  721.                 return -1;
  722.             } else if((errno = pwait(up)) != 0){
  723.                 return -1;
  724.             }
  725.         }
  726.         if(cb.rip == NULLRIP){
  727.             /* Connection went away */
  728.             errno = ENOTCONN;
  729.             return -1;
  730.         }
  731.         bp = dequeue(&cb.rip->rcvq);
  732.         ntohip(&ip,&bp);
  733.  
  734.         cnt = len_p(bp);
  735.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  736.             remote.in = (struct sockaddr_in *)from;
  737.             remote.in->sin_family = AF_INET;
  738.             remote.in->sin_addr.s_addr = ip.source;
  739.             remote.in->sin_port = 0;
  740.             *fromlen = SOCKSIZE;
  741.         }
  742.         break;
  743. #ifdef    AX25
  744.     case TYPE_AX25I:
  745.         while((cb.ax25 = up->cb.ax25) != NULLAX25
  746.          && (bp = recv_ax25(cb.ax25,(int16)0)) == NULLBUF){
  747.             if(up->noblock){
  748.                 errno = EWOULDBLOCK;
  749.                 return -1;
  750.             } else if((errno = pwait(up)) != 0){
  751.                 return -1;
  752.             }
  753.         }
  754.         if(cb.ax25 == NULLAX25){
  755.             /* Connection went away */
  756.             errno = ENOTCONN;
  757.             return -1;
  758.         }
  759.         cnt = bp->cnt;
  760.         break;
  761.     case TYPE_AX25UI:
  762.         while(s == Axui_sock && Bcq == NULLBUF){
  763.             if(up->noblock){
  764.                 errno = EWOULDBLOCK;
  765.                 return -1;
  766.             } else if((errno = pwait(&Bcq)) != 0){
  767.                 return -1;
  768.             }
  769.         }
  770.         if(s != Axui_sock){
  771.             errno = ENOTCONN;
  772.             return -1;
  773.         }
  774.         bp = dequeue(&Bcq);
  775.  
  776.         if(from != NULLCHAR && fromlen != NULLINT
  777.            && *fromlen >= sizeof(struct sockaddr_ax)){
  778.             pullup(&bp,from,sizeof(struct sockaddr_ax));
  779.             *fromlen = sizeof(struct sockaddr_ax);
  780.         } else {
  781.             pullup(&bp,NULLCHAR,sizeof(struct sockaddr_ax));
  782.         }
  783.         cnt = len_p(bp);
  784.         break;
  785. #endif
  786. #ifdef NETROM
  787.     case TYPE_NETROML3:
  788.         while((cb.rnr = up->cb.rnr) != NULLRNR
  789.          && cb.rnr->rcvq == NULLBUF){
  790.             if(up->noblock){
  791.                 errno = EWOULDBLOCK;
  792.                 return -1;
  793.             } else if((errno = pwait(up)) != 0){
  794.                 return -1;
  795.             }
  796.         }
  797.         if(cb.rnr == NULLRNR){
  798.             /* Connection went away */
  799.             errno = ENOTCONN;
  800.             return -1;
  801.         }
  802.         bp = dequeue(&cb.rnr->rcvq);
  803.         ntohnr3(&n3hdr,&bp);
  804.         cnt = len_p(bp);
  805.         if(from != NULLCHAR && fromlen != NULLINT
  806.            && *fromlen >= sizeof(struct sockaddr_nr)){
  807.             remote.nr = (struct sockaddr_nr *)from;
  808.             remote.nr->nr_family = AF_NETROM;
  809.             /* The callsign of the local user is not part of
  810.                NET/ROM level 3, so that field is not used here */
  811.             memcpy(remote.nr->nr_addr.node,n3hdr.source,AXALEN);
  812.             *fromlen = sizeof(struct sockaddr_nr);
  813.         }
  814.         break;
  815.     case TYPE_NETROML4:
  816.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB
  817.          && (bp = recv_nr4(cb.nr4,(int16)0)) == NULLBUF){
  818.             if(up->noblock){
  819.                 errno = EWOULDBLOCK;
  820.                 return -1;
  821.             } else if((errno = pwait(up)) != 0){
  822.                 return -1;
  823.             }
  824.         }
  825.         if(cb.nr4 == NULLNR4CB){
  826.             /* Connection went away */
  827.             errno = ENOTCONN;
  828.             return -1;
  829.         }
  830.         cnt = bp->cnt;
  831.         break;
  832. #endif
  833.     }
  834.     if(bpp != NULLBUFP)
  835.         *bpp = bp;
  836.     else
  837.         free_p(bp);
  838.     return cnt;
  839. }
  840. /* Low level send routine; user supplies mbuf for transmission. More
  841.  * efficient than send() or sendto(), the higher level interfaces.
  842.  * The "to" and "tolen" parameters are ignored on connection-oriented
  843.  * sockets.
  844.  *
  845.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  846.  */
  847. int
  848. send_mbuf(s,bp,flags,to,tolen)
  849. int s;            /* Socket index */
  850. struct mbuf *bp;    /* Buffer to send */
  851. int flags;        /* not currently used */
  852. char *to;        /* Destination, only for datagrams */
  853. int tolen;        /* Length of destination */
  854. {
  855.     register struct usock *up;
  856.     union cb cb;
  857.     union sp local,remote;
  858.     struct socket lsock,fsock;
  859.     int cnt;
  860.  
  861.     if((up = itop(s)) == NULLUSOCK){
  862.         free_p(bp);
  863.         errno = EBADF;
  864.         return -1;
  865.     }
  866. #ifndef    notdef
  867.     if(up->obuf != NULLBUF){
  868.         /* If there's unflushed output, send it.
  869.          * Note the importance of clearing up->obuf
  870.          * before the recursive call!
  871.          */
  872.         struct mbuf *bp1;
  873.  
  874.         bp1 = up->obuf;
  875.         up->obuf = NULLBUF;
  876.         send_mbuf(s,bp1,flags,to,tolen);
  877.     }
  878. #endif
  879.     if(up->name == NULLCHAR){
  880.         /* Automatic local name assignment for datagram sockets */
  881.         switch(up->type){
  882.         case TYPE_LOCAL_STREAM:
  883.         case TYPE_LOCAL_DGRAM:
  884.             break;    /* no op */
  885.         case TYPE_UDP:
  886.         case TYPE_RAW:
  887.             autobind(s,AF_INET);
  888.             break;
  889. #ifdef    AX25
  890.         case TYPE_AX25UI:
  891.             autobind(s,AF_AX25);
  892.             break;
  893. #endif
  894. #ifdef    NETROM
  895.         case TYPE_NETROML3:
  896.         case TYPE_NETROML4:
  897.             autobind(s,AF_NETROM);
  898.             break;
  899. #endif
  900.         default:
  901.             free_p(bp);
  902.             errno = ENOTCONN;
  903.             return -1;
  904.         }
  905.     }
  906.     cnt = len_p(bp);
  907.     switch(up->type){
  908.     case TYPE_LOCAL_DGRAM:
  909.         if(up->cb.local->peer == NULLUSOCK){
  910.             free_p(bp);
  911.             errno = ENOTCONN;
  912.             return -1;
  913.         }
  914.         enqueue(&up->cb.local->peer->cb.local->q,bp);
  915.         psignal(up->cb.local->peer,0);
  916.         /* If high water mark has been reached, block */
  917.         while(up->cb.local->peer != NULLUSOCK &&
  918.               len_q(up->cb.local->peer->cb.local->q) >=
  919.               up->cb.local->peer->cb.local->hiwat){
  920.             if(up->noblock){
  921.                 errno = EWOULDBLOCK;
  922.                 return -1;
  923.             } else if((errno = pwait(up->cb.local->peer)) != 0){
  924.                 return -1;
  925.             }
  926.         }
  927.         if(up->cb.local->peer == NULLUSOCK){
  928.             errno = ENOTCONN;
  929.             return -1;
  930.         }
  931.         break;
  932.     case TYPE_LOCAL_STREAM:
  933.         if(up->cb.local->peer == NULLUSOCK){
  934.             free_p(bp);
  935.             errno = ENOTCONN;
  936.             return -1;
  937.         }
  938.         append(&up->cb.local->peer->cb.local->q,bp);
  939.         psignal(up->cb.local->peer,0);
  940.         /* If high water mark has been reached, block */
  941.         while(up->cb.local->peer != NULLUSOCK &&
  942.               len_p(up->cb.local->peer->cb.local->q) >=
  943.               up->cb.local->peer->cb.local->hiwat){
  944.             if(up->noblock){
  945.                 errno = EWOULDBLOCK;
  946.                 return -1;
  947.             } else if((errno = pwait(up->cb.local->peer)) != 0){
  948.                 return -1;
  949.             }
  950.         }
  951.         if(up->cb.local->peer == NULLUSOCK){
  952.             errno = ENOTCONN;
  953.             return -1;
  954.         }
  955.         break;
  956.     case TYPE_TCP:
  957.         if((cb.tcb = up->cb.tcb) == NULLTCB){
  958.             free_p(bp);
  959.             errno = ENOTCONN;
  960.             return -1;
  961.         }        
  962.         cnt = send_tcp(cb.tcb,bp);
  963.  
  964.         while((cb.tcb = up->cb.tcb) != NULLTCB &&
  965.          cb.tcb->sndcnt > cb.tcb->window){
  966.             /* Send queue is full */
  967.             if(up->noblock){
  968.                 errno = EWOULDBLOCK;
  969.                 return -1;
  970.             } else if((errno = pwait(up)) != 0){
  971.                 return -1;
  972.             }
  973.         }
  974.          if(cb.tcb == NULLTCB){
  975.             errno = ENOTCONN;
  976.             return -1;
  977.         }
  978.         break;
  979.     case TYPE_UDP:
  980.         local.in = (struct sockaddr_in *)up->name;
  981.         lsock.address = local.in->sin_addr.s_addr;
  982.         lsock.port = local.in->sin_port;
  983.         if(to != NULLCHAR)
  984.             remote.in = (struct sockaddr_in *)to;
  985.         else if(up->peername != NULLCHAR)
  986.             remote.in = (struct sockaddr_in *)up->peername;
  987.         else {
  988.             errno = ENOTCONN;
  989.             return -1;
  990.         }    
  991.         fsock.address = remote.in->sin_addr.s_addr;
  992.         fsock.port = remote.in->sin_port;
  993.         send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  994.         break;
  995.     case TYPE_RAW:
  996.         local.in = (struct sockaddr_in *)up->name;
  997.         if(to != NULLCHAR)
  998.             remote.in = (struct sockaddr_in *)to;
  999.         else if(up->peername != NULLCHAR)
  1000.             remote.in = (struct sockaddr_in *)up->peername;
  1001.         else {
  1002.             errno = ENOTCONN;
  1003.             return -1;
  1004.         }    
  1005.         ip_send(local.in->sin_addr.s_addr,remote.in->sin_addr.s_addr,
  1006.             (char)up->cb.rip->protocol,0,0,bp,0,0,0);
  1007.         break;
  1008. #ifdef    AX25
  1009.     case TYPE_AX25I:
  1010.         if((cb.ax25 = up->cb.ax25) == NULLAX25){
  1011.             free_p(bp);
  1012.             errno = ENOTCONN;
  1013.             return -1;
  1014.         }
  1015.         send_ax25(cb.ax25,bp,PID_NO_L3);
  1016.  
  1017.         while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  1018.          len_q(cb.ax25->txq) * cb.ax25->paclen > cb.ax25->window){
  1019.             if(up->noblock){
  1020.                 errno = EWOULDBLOCK;
  1021.                 return -1;
  1022.             } else if((errno = pwait(up)) != 0){
  1023.                 return -1;
  1024.             }
  1025.         }
  1026.         if(cb.ax25 == NULLAX25){
  1027.             errno = EBADF;
  1028.             return -1;
  1029.         }
  1030.         break;
  1031.     case TYPE_AX25UI:
  1032.         local.ax = (struct sockaddr_ax *)up->name;
  1033.         if(to != NULLCHAR)
  1034.             remote.ax = (struct sockaddr_ax *)to;
  1035.         else if(up->peername != NULLCHAR)
  1036.             remote.ax = (struct sockaddr_ax *)up->peername;
  1037.         else {
  1038.             errno = ENOTCONN;
  1039.             return -1;
  1040.         }
  1041.         ax_output(if_lookup(remote.ax->iface),
  1042.               remote.ax->ax25_addr,
  1043.               local.ax->ax25_addr,PID_NO_L3,bp);
  1044.         break;
  1045. #endif
  1046. #ifdef NETROM
  1047.     case TYPE_NETROML3:
  1048.         if(len_p(bp) > NR4MAXINFO) {
  1049.             free_p(bp);
  1050.             errno = EMSGSIZE;
  1051.             return -1;
  1052.         }
  1053.         local.nr = (struct sockaddr_nr *)up->name;
  1054.         if(to != NULLCHAR)
  1055.             remote.nr = (struct sockaddr_nr *)to;
  1056.         else if(up->peername != NULLCHAR)
  1057.             remote.nr = (struct sockaddr_nr *)up->peername;
  1058.         else {
  1059.             errno = ENOTCONN;
  1060.             return -1;
  1061.         }    
  1062.         /* The NETROM username is always ignored in outgoing traffic */
  1063.         nr_sendraw(remote.nr->nr_addr.node,
  1064.          up->cb.rnr->protocol,up->cb.rnr->protocol,bp);
  1065.         break;
  1066.     case TYPE_NETROML4:
  1067.         if((cb.nr4 = up->cb.nr4) == NULLNR4CB) {
  1068.             free_p(bp);
  1069.             errno = ENOTCONN;
  1070.             return -1;
  1071.         }
  1072.         if(len_p(bp) > NR4MAXINFO){ /* reject big packets */
  1073.             free_p(bp);
  1074.             errno = EMSGSIZE;
  1075.             return -1;
  1076.         }
  1077.         send_nr4(cb.nr4,bp);
  1078.  
  1079.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB &&
  1080.          cb.nr4->nbuffered >= cb.nr4->window){
  1081.             if(up->noblock){
  1082.                 errno = EWOULDBLOCK;
  1083.                 return -1;
  1084.             } else if((errno = pwait(up)) != 0){
  1085.                 errno = EINTR;
  1086.                 return -1;
  1087.             }
  1088.         }
  1089.         if(cb.nr4 == NULLNR4CB){
  1090.             errno = EBADF;
  1091.             return -1;
  1092.         }
  1093.         break;
  1094. #endif
  1095.     }    
  1096.     return cnt;
  1097. }
  1098. /* Return local name passed in an earlier bind() call */
  1099. int
  1100. getsockname(s,name,namelen)
  1101. int s;        /* Socket index */
  1102. char *name;    /* Place to stash name */
  1103. int *namelen;    /* Length of same */
  1104. {
  1105.     register struct usock *up;
  1106.  
  1107.     if((up = itop(s)) == NULLUSOCK){
  1108.         errno = EBADF;
  1109.         return -1;
  1110.     }
  1111.     if(name == NULLCHAR || namelen == (int *)NULL){
  1112.         errno = EFAULT;
  1113.         return -1;
  1114.     }
  1115.     if(up->name == NULLCHAR){
  1116.         /* Not bound yet */
  1117.         *namelen = 0;
  1118.         return 0;
  1119.     }
  1120.     if(up->name != NULLCHAR){
  1121.         *namelen = min(*namelen,up->namelen);
  1122.         memcpy(name,up->name,*namelen);
  1123.     }
  1124.     return 0;
  1125. }
  1126. /* Get remote name, returning result of earlier connect() call. */
  1127. int
  1128. getpeername(s,peername,peernamelen)
  1129. int s;            /* Socket index */
  1130. char *peername;        /* Place to stash name */
  1131. int *peernamelen;    /* Length of same */
  1132. {
  1133.     register struct usock *up;
  1134.  
  1135.     if((up = itop(s)) == NULLUSOCK){
  1136.         errno = EBADF;
  1137.         return -1;
  1138.     }
  1139.     if(up->peername == NULLCHAR){
  1140.         errno = ENOTCONN;
  1141.         return -1;
  1142.     }
  1143.     if(peername == NULLCHAR || peernamelen == (int *)NULL){
  1144.         errno = EFAULT;
  1145.         return -1;
  1146.     }
  1147.     *peernamelen = min(*peernamelen,up->peernamelen);
  1148.     memcpy(peername,up->peername,*peernamelen);
  1149.     return 0;
  1150. }
  1151. /* Return length of protocol queue, either send or receive. */
  1152. int
  1153. socklen(s,rtx)
  1154. int s;        /* Socket index */
  1155. int rtx;    /* 0 = receive queue, 1 = transmit queue */
  1156. {
  1157.     register struct usock *up;
  1158.     int len = -1;
  1159.  
  1160.     if((up = itop(s)) == NULLUSOCK){
  1161.         errno = EBADF;
  1162.         return -1;
  1163.     }
  1164.     if(up->cb.p == NULLCHAR){
  1165.         errno = ENOTCONN;
  1166.         return -1;
  1167.     }
  1168.     if(rtx < 0 || rtx > 1){
  1169.         errno = EINVAL;
  1170.         return -1;
  1171.     }
  1172.     switch(up->type){
  1173.     case TYPE_LOCAL_DGRAM:
  1174.         switch(rtx){
  1175.         case 0:
  1176.             len = len_q(up->cb.local->q);
  1177.             break;
  1178.         case 1:
  1179.             if(up->cb.local->peer != NULLUSOCK)
  1180.                 len = len_q(up->cb.local->peer->cb.local->q);
  1181.             break;
  1182.         }
  1183.         break;
  1184.     case TYPE_LOCAL_STREAM:
  1185.         switch(rtx){
  1186.         case 0:
  1187.             len = len_p(up->cb.local->q) + len_p(up->ibuf);
  1188.             break;
  1189.         case 1:
  1190.             if(up->cb.local->peer != NULLUSOCK)
  1191.                 len = len_p(up->cb.local->peer->cb.local->q)
  1192.                       + len_p(up->obuf);
  1193.             break;
  1194.         }
  1195.         break;
  1196.     case TYPE_TCP:
  1197.         switch(rtx){
  1198.         case 0:
  1199.             len = up->cb.tcb->rcvcnt + len_p(up->ibuf);
  1200.             break;
  1201.         case 1:
  1202.             len = up->cb.tcb->sndcnt + len_p(up->obuf);
  1203.             break;
  1204.         }
  1205.         break;
  1206.     case TYPE_UDP:
  1207.         switch(rtx){
  1208.         case 0:
  1209.             len = up->cb.udp->rcvcnt;
  1210.             break;
  1211.         case 1:
  1212.             len = 0;
  1213.             break;
  1214.         }
  1215.         break;
  1216. #ifdef    AX25
  1217.     case TYPE_AX25I:
  1218.         switch(rtx){
  1219.         case 0:
  1220.             len = len_p(up->cb.ax25->rxq) + len_p(up->ibuf);
  1221.             break;
  1222.         case 1:    /* Number of packets, not bytes */
  1223.             len = len_q(up->cb.ax25->txq);
  1224.             if(up->obuf != NULLBUF)
  1225.                 len++;
  1226.         }
  1227.         break;
  1228.     case TYPE_AX25UI:
  1229.         switch(rtx){    
  1230.         case 0:
  1231.             len = len_q(Bcq);
  1232.             break;
  1233.         case 1:
  1234.             len = 0;        
  1235.             break;
  1236.         }
  1237.         break;
  1238. #endif
  1239. #ifdef NETROM
  1240.     case TYPE_NETROML3:
  1241.         switch(rtx){    
  1242.         case 0:
  1243.             len = len_q(up->cb.rnr->rcvq);
  1244.             break;
  1245.         case 1:
  1246.             len = 0;        
  1247.         }
  1248.         break;
  1249.     case TYPE_NETROML4:
  1250.         switch(rtx){
  1251.         case 0:
  1252.             len = len_p(up->cb.nr4->rxq) + len_p(up->obuf);
  1253.             break;
  1254.         case 1:    /* Number of packets, not bytes */
  1255.             len = len_q(up->cb.nr4->txq);
  1256.             if(up->obuf != NULLBUF)
  1257.                 len++;
  1258.             break;
  1259.         }
  1260.         break;
  1261. #endif
  1262.     case TYPE_RAW:
  1263.         switch(rtx){    
  1264.         case 0:
  1265.             len = len_q(up->cb.rip->rcvq);
  1266.             break;
  1267.         case 1:
  1268.             len = 0;        
  1269.             break;
  1270.         }
  1271.         break;
  1272.     }
  1273.     return len;
  1274. }
  1275. /* Force retransmission. Valid only for connection-oriented sockets. */
  1276. int
  1277. sockkick(s)
  1278. int s;    /* Socket index */
  1279. {
  1280.     register struct usock *up;
  1281.  
  1282.     if((up = itop(s)) == NULLUSOCK){
  1283.         errno = EBADF;
  1284.         return -1;
  1285.     }
  1286.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  1287.         errno = EINVAL;
  1288.         return -1;
  1289.     }
  1290.     if(up->cb.p == NULLCHAR){
  1291.         errno = ENOTCONN;
  1292.         return -1;
  1293.     }
  1294.     switch(up->type){
  1295.     case TYPE_TCP:
  1296.         kick_tcp(up->cb.tcb);
  1297.         break;
  1298. #ifdef    AX25
  1299.     case TYPE_AX25I:
  1300.         kick_ax25(up->cb.ax25);
  1301.         break;
  1302. #endif
  1303. #ifdef NETROM
  1304.     case TYPE_NETROML4:
  1305.         kick_nr4(up->cb.nr4);
  1306.         break;
  1307. #endif
  1308.     default:
  1309.         /* Datagram sockets can't be kicked */
  1310.         errno = EOPNOTSUPP;
  1311.         return -1;
  1312.     }
  1313.     return 0;
  1314. }
  1315.  
  1316. /* Change owner of socket, return previous owner */
  1317. struct proc *
  1318. sockowner(s,newowner)
  1319. int s;            /* Socket index */
  1320. struct proc *newowner;    /* Process table address of new owner */
  1321. {
  1322.     register struct usock *up;
  1323.     struct proc *pp;
  1324.  
  1325.     if((up = itop(s)) == NULLUSOCK){
  1326.         errno = EBADF;
  1327.         return NULLPROC;
  1328.     }
  1329.     pp = up->owner;
  1330.     if(newowner != NULLPROC)
  1331.         up->owner = newowner;
  1332.     return pp;
  1333. }
  1334. /* Close down a socket three ways. Type 0 means "no more receives"; this
  1335.  * replaces the incoming data upcall with a routine that discards further
  1336.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  1337.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  1338.  * as "abort the connection".
  1339.  */
  1340. int
  1341. shutdown(s,how)
  1342. int s;        /* Socket index */
  1343. int how;    /* (see above) */
  1344. {
  1345.     register struct usock *up;
  1346.  
  1347.     if((up = itop(s)) == NULLUSOCK){
  1348.         errno = EBADF;
  1349.         return -1;
  1350.     }
  1351.     if(up->cb.p == NULLCHAR){
  1352.         errno = ENOTCONN;
  1353.         return -1;
  1354.     }
  1355.     switch(up->type){
  1356.     case TYPE_LOCAL_DGRAM:
  1357.     case TYPE_LOCAL_STREAM:
  1358.         if(up->cb.local->q == NULLBUF)
  1359.             close_s(s);
  1360.         else
  1361.             up->cb.local->flags = LOC_SHUTDOWN;
  1362.         break;
  1363.     case TYPE_TCP:
  1364.         switch(how){
  1365.         case 0:    /* No more receives -- replace upcall */
  1366.             up->cb.tcb->r_upcall = trdiscard;
  1367.             break;
  1368.         case 1:    /* Send EOF */
  1369.             close_tcp(up->cb.tcb);
  1370.             break;
  1371.         case 2:    /* Blow away TCB */
  1372.             reset_tcp(up->cb.tcb);
  1373.             up->cb.tcb = NULLTCB;
  1374.             break;
  1375.         }
  1376.         break;
  1377. #ifdef    AX25
  1378.     case TYPE_AX25UI:
  1379.         close_s(s);
  1380.         break;
  1381.     case TYPE_AX25I:
  1382.         switch(how){
  1383.         case 0:
  1384.         case 1:    /* Attempt regular disconnect */
  1385.             disc_ax25(up->cb.ax25);
  1386.             break;
  1387.         case 2: /* Blow it away */
  1388.             reset_ax25(up->cb.ax25);
  1389.             up->cb.ax25 = NULLAX25;
  1390.             break;
  1391.         }
  1392.         break;        
  1393. #endif
  1394. #ifdef    NETROM
  1395.     case TYPE_NETROML3:
  1396.         close_s(s);
  1397.         break;
  1398.     case TYPE_NETROML4:
  1399.         switch(how){
  1400.         case 0:
  1401.         case 1:    /* Attempt regular disconnect */
  1402.             disc_nr4(up->cb.nr4);
  1403.             break;
  1404.         case 2: /* Blow it away */
  1405.             reset_nr4(up->cb.nr4);
  1406.             up->cb.nr4 = NULLNR4CB;
  1407.             break;
  1408.         }
  1409.         break;        
  1410. #endif
  1411.     case TYPE_RAW:
  1412.     case TYPE_UDP:
  1413.         close_s(s);
  1414.         break;
  1415.     default:
  1416.         errno = EOPNOTSUPP;
  1417.         return -1;
  1418.     }
  1419.     psignal(up,0);
  1420.     return 0;
  1421. }
  1422. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1423.  * TCP socket, if possible
  1424.  */
  1425. int
  1426. close_s(s)
  1427. int s;        /* Socket index */
  1428. {
  1429.     register struct usock *up;
  1430.  
  1431.     if((up = itop(s)) == NULLUSOCK){
  1432.         errno = EBADF;
  1433.         return -1;
  1434.     }
  1435.     if(--up->refcnt > 0)
  1436.         return 0;    /* Others are still using it */
  1437.     usflush(s);
  1438.     if(up->ibuf != NULLBUF){
  1439.         free_p(up->ibuf);
  1440.         up->ibuf = NULLBUF;
  1441.     }
  1442.     switch(up->type){
  1443.     case TYPE_LOCAL_STREAM:
  1444.     case TYPE_LOCAL_DGRAM:
  1445.         if(up->cb.local->peer != NULLUSOCK){
  1446.             up->cb.local->peer->cb.local->peer = NULLUSOCK;
  1447.             psignal(up->cb.local->peer,0);
  1448.         }
  1449.         free_q(&up->cb.local->q);
  1450.         free(up->cb.local);
  1451.         break;
  1452.     case TYPE_TCP:
  1453.         if(up->cb.tcb != NULLTCB){    /* In case it's been reset */
  1454.             up->cb.tcb->r_upcall = trdiscard;
  1455.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1456.             up->cb.tcb->user = -1;
  1457.             close_tcp(up->cb.tcb);
  1458.         }
  1459.         break;
  1460.     case TYPE_UDP:
  1461.         if(up->cb.udp != NULLUDP){
  1462.             del_udp(up->cb.udp);
  1463.         }
  1464.         break;
  1465. #ifdef    AX25
  1466.     case TYPE_AX25I:
  1467.         if(up->cb.ax25 != NULLAX25){
  1468.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1469.             up->cb.ax25->user = -1;
  1470.             disc_ax25(up->cb.ax25);
  1471.         }
  1472.         break;
  1473.     case TYPE_AX25UI:
  1474.         Axui_sock = -1;
  1475.         free_q(&Bcq);
  1476.         psignal(&Bcq,0);    /* Unblock any reads */
  1477.         break;
  1478. #endif
  1479. #ifdef    NETROM
  1480.     case TYPE_NETROML3:
  1481.         del_rnr(up->cb.rnr);
  1482.         break;
  1483.     case TYPE_NETROML4:
  1484.         if(up->cb.nr4 != NULLNR4CB){
  1485.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1486.             up->cb.nr4->user = -1;
  1487.             disc_nr4(up->cb.nr4);
  1488.         }
  1489.         break;
  1490. #endif
  1491.     case TYPE_RAW:
  1492.         del_ip(up->cb.rip);
  1493.         break;
  1494.     default:
  1495.         errno = EOPNOTSUPP;
  1496.         return -1;
  1497.     }
  1498. #ifdef    LZW
  1499.     if(up->zout != NULLLZW || up->zin != NULLLZW)
  1500.         lzwfree(up);
  1501. #endif
  1502.     free(up->name);
  1503.     free(up->peername);
  1504.  
  1505.     up->cb.p = NULLCHAR;
  1506.     up->name = up->peername = NULLCHAR;
  1507.     up->type = NOTUSED;
  1508.     psignal(up,0);    /* Wake up anybody doing an accept() or recv() */
  1509.     return 0;
  1510. }
  1511. /* Increment reference count for specified socket */
  1512. int
  1513. usesock(s)
  1514. int s;
  1515. {
  1516.     struct usock *up;
  1517.  
  1518.     if((up = itop(s)) == NULLUSOCK){
  1519.         errno = EBADF;
  1520.         return -1;
  1521.     }
  1522.     up->refcnt++;
  1523.     return 0;
  1524. }
  1525. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1526. void
  1527. freesock(pp)
  1528. struct proc *pp;
  1529. {
  1530.     register struct usock *up;
  1531.     register int i;
  1532.  
  1533.     for(i=SOCKBASE;i < Nusock+SOCKBASE;i++){
  1534.         up = itop(i);
  1535.         if(up != NULLUSOCK && up->type != NOTUSED && up->owner == pp)
  1536.             shutdown(i,2);
  1537.     }
  1538. }
  1539. /* Start of internal subroutines */
  1540.  
  1541. /* Raw IP receive upcall routine */
  1542. static void
  1543. rip_recv(rp)
  1544. struct raw_ip *rp;
  1545. {
  1546.     psignal(itop(rp->user),1);
  1547.     pwait(NULL);
  1548. }
  1549.  
  1550. /* UDP receive upcall routine */
  1551. static void
  1552. s_urcall(iface,udp,cnt)
  1553. struct iface *iface;
  1554. struct udp_cb *udp;
  1555. int cnt;
  1556. {
  1557.     psignal(itop(udp->user),1);
  1558.     pwait(NULL);
  1559. }
  1560. /* TCP receive upcall routine */
  1561. static void
  1562. s_trcall(tcb,cnt)
  1563. struct tcb *tcb;
  1564. int cnt;
  1565. {
  1566.     /* Wake up anybody waiting for data, and let them run */
  1567.     psignal(itop(tcb->user),1);
  1568.     pwait(NULL);
  1569. }
  1570. /* TCP transmit upcall routine */
  1571. static void
  1572. s_ttcall(tcb,cnt)
  1573. struct tcb *tcb;
  1574. int cnt;
  1575. {
  1576.     /* Wake up anybody waiting to send data, and let them run */
  1577.     psignal(itop(tcb->user),1);
  1578.     pwait(NULL);
  1579. }
  1580. /* TCP state change upcall routine */
  1581. static void
  1582. s_tscall(tcb,old,new)
  1583. struct tcb *tcb;
  1584. int old,new;
  1585. {
  1586.     int s,ns;
  1587.     struct usock *up,*nup,*oup;
  1588.     union sp sp;
  1589.  
  1590.     s = tcb->user;
  1591.     oup = up = itop(s);
  1592.  
  1593.     switch(new){
  1594.     case TCP_CLOSED:
  1595.         /* Clean up. If the user has already closed the socket,
  1596.          * then up will be null (s was set to -1 by the close routine).
  1597.          * If not, then this is an abnormal close (e.g., a reset)
  1598.          * and clearing out the pointer in the socket structure will
  1599.          * prevent any further operations on what will be a freed
  1600.          * control block. Also wake up anybody waiting on events
  1601.          * related to this tcb so they will notice it disappearing.
  1602.          */
  1603.         if(up != NULLUSOCK){
  1604.             up->cb.tcb = NULLTCB;
  1605.             up->errcodes[0] = tcb->reason;
  1606.             up->errcodes[1] = tcb->type;
  1607.             up->errcodes[2] = tcb->code;
  1608.         }
  1609.         del_tcp(tcb);
  1610.         break;
  1611.     case TCP_SYN_RECEIVED:
  1612.         /* Handle an incoming connection. If this is a server TCB,
  1613.          * then we're being handed a "clone" TCB and we need to
  1614.          * create a new socket structure for it. In either case,
  1615.          * find out who we're talking to and wake up the guy waiting
  1616.          * for the connection.
  1617.          */
  1618.         if(tcb->flags.clone){
  1619.             /* Clone the socket */
  1620.             ns = socket(AF_INET,SOCK_STREAM,0);
  1621.             nup = itop(ns);
  1622.             ASSIGN(*nup,*up);
  1623.             tcb->user = ns;
  1624.             nup->cb.tcb = tcb;
  1625.             /* Allocate new memory for the name areas */
  1626.             nup->name = mallocw(SOCKSIZE);
  1627.             nup->peername = mallocw(SOCKSIZE);
  1628.             /* Store the new socket # in the old one */
  1629.             up->rdysock = ns;
  1630.             up = nup;
  1631.             s = ns;
  1632.         } else {
  1633.             /* Allocate space for the peer's name */
  1634.             up->peername = mallocw(SOCKSIZE);
  1635.             /* Store the old socket # in the old socket */
  1636.             up->rdysock = s;
  1637.         }
  1638.         /* Load the addresses. Memory for the name has already
  1639.          * been allocated, either above or in the original bind.
  1640.          */
  1641.         sp.p = up->name;
  1642.         sp.in->sin_family = AF_INET;
  1643.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1644.         sp.in->sin_port = up->cb.tcb->conn.local.port;
  1645.         up->namelen = SOCKSIZE;
  1646.  
  1647.         sp.p = up->peername;
  1648.         sp.in->sin_family = AF_INET;
  1649.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1650.         sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1651.         up->peernamelen = SOCKSIZE;
  1652.  
  1653.         /* Wake up the guy accepting it, and let him run */
  1654.         psignal(oup,1);
  1655.         pwait(NULL);
  1656.         break;
  1657.     default:    /* Ignore all other state transitions */
  1658.         break;
  1659.     }
  1660.     psignal(up,0);    /* In case anybody's waiting */
  1661. }
  1662. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1663.  * close_s until the TCB disappears.
  1664.  */
  1665. static void
  1666. trdiscard(tcb,cnt)
  1667. struct tcb *tcb;
  1668. int cnt;
  1669. {
  1670.     struct mbuf *bp;
  1671.  
  1672.     recv_tcp(tcb,&bp,(int16)cnt);
  1673.     free_p(bp);
  1674. }
  1675. #ifdef    AX25
  1676. /* AX.25 receive upcall */
  1677. void
  1678. s_arcall(axp,cnt)
  1679. struct ax25_cb *axp;
  1680. int cnt;
  1681. {
  1682.     int ns;
  1683.     struct usock *up,*nup,*oup;
  1684.     union sp sp;
  1685.  
  1686.     up = itop(axp->user);
  1687.     /* When AX.25 data arrives for the first time the AX.25 listener
  1688.        is notified, if active. If the AX.25 listener is a server its
  1689.        socket is duplicated in the same manner as in s_tscall().
  1690.      */
  1691.     if (Axi_sock != -1 && axp->user == -1) {
  1692.         oup = up = itop(Axi_sock);
  1693.         /* From now on, use the same upcalls as the listener */
  1694.         axp->t_upcall = up->cb.ax25->t_upcall;
  1695.         axp->r_upcall = up->cb.ax25->r_upcall;
  1696.         axp->s_upcall = up->cb.ax25->s_upcall;
  1697.         if (up->cb.ax25->flags.clone) {
  1698.             /* Clone the socket */
  1699.             ns = socket(AF_AX25,SOCK_STREAM,0);
  1700.             nup = itop(ns);
  1701.             ASSIGN(*nup,*up);
  1702.             axp->user = ns;
  1703.             nup->cb.ax25 = axp;
  1704.             /* Allocate new memory for the name areas */
  1705.             nup->name = mallocw(sizeof(struct sockaddr_ax));
  1706.             nup->peername = mallocw(sizeof(struct sockaddr_ax));
  1707.             /* Store the new socket # in the old one */
  1708.             up->rdysock = ns;
  1709.             up = nup;
  1710.         } else {
  1711.             axp->user = Axi_sock;
  1712.             del_ax25(up->cb.ax25);
  1713.             up->cb.ax25 = axp;
  1714.             /* Allocate space for the peer's name */
  1715.             up->peername = mallocw(sizeof(struct sockaddr_ax));
  1716.             /* Store the old socket # in the old socket */
  1717.             up->rdysock = Axi_sock;
  1718.         }
  1719.         /* Load the addresses. Memory for the name has already
  1720.          * been allocated, either above or in the original bind.
  1721.          */
  1722.         sp.p = up->name;
  1723.         sp.ax->sax_family = AF_AX25;
  1724.         memcpy(sp.ax->ax25_addr,axp->local,AXALEN);
  1725.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1726.         up->namelen = sizeof(struct sockaddr_ax);
  1727.  
  1728.         sp.p = up->peername;
  1729.         sp.ax->sax_family = AF_AX25;
  1730.         memcpy(sp.ax->ax25_addr,axp->remote,AXALEN);
  1731.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1732.         up->peernamelen = sizeof(struct sockaddr_ax);
  1733.         /* Wake up the guy accepting it, and let him run */
  1734.         psignal(oup,1);
  1735.         pwait(NULL);
  1736.         return;
  1737.     }
  1738.     /* Wake up anyone waiting, and let them run */
  1739.     psignal(up,1);
  1740.     pwait(NULL);
  1741. }
  1742. /* AX.25 transmit upcall */
  1743. void
  1744. s_atcall(axp,cnt)
  1745. struct ax25_cb *axp;
  1746. int cnt;
  1747. {
  1748.     /* Wake up anyone waiting, and let them run */
  1749.     psignal(itop(axp->user),1);
  1750.     pwait(NULL);
  1751. }
  1752. /* AX25 state change upcall routine */
  1753. void
  1754. s_ascall(axp,old,new)
  1755. register struct ax25_cb *axp;
  1756. int old,new;
  1757. {
  1758.     int s;
  1759.     struct usock *up;
  1760.  
  1761.     s = axp->user;
  1762.     up = itop(s);
  1763.  
  1764.     switch(new){
  1765.     case LAPB_DISCONNECTED:
  1766.         /* Clean up. If the user has already closed the socket,
  1767.          * then up will be null (s was set to -1 by the close routine).
  1768.          * If not, then this is an abnormal close (e.g., a reset)
  1769.          * and clearing out the pointer in the socket structure will
  1770.          * prevent any further operations on what will be a freed
  1771.          * control block. Also wake up anybody waiting on events
  1772.          * related to this block so they will notice it disappearing.
  1773.          */
  1774.         if(up != NULLUSOCK){
  1775.             up->errcodes[0] = axp->reason;
  1776.             up->cb.ax25 = NULLAX25;
  1777.         }
  1778.         del_ax25(axp);
  1779.         break;
  1780.     default:    /* Other transitions are ignored */
  1781.         break;
  1782.     }
  1783.     psignal(up,0);    /* In case anybody's waiting */
  1784. }
  1785. #endif
  1786. #ifdef NETROM
  1787. /* NET/ROM receive upcall routine */
  1788. static void
  1789. s_nrcall(struct nr4cb *cb, int16 cnt)
  1790. {
  1791.     /* Wake up anybody waiting for data, and let them run */
  1792.     psignal(itop(cb->user),1);
  1793.     pwait(NULL);
  1794. }
  1795. /* NET/ROM transmit upcall routine */
  1796. static void
  1797. s_ntcall(struct nr4cb *cb, int16 cnt)
  1798. {
  1799.     /* Wake up anybody waiting to send data, and let them run */
  1800.    psignal(itop(cb->user),1);
  1801.     pwait(NULL);
  1802. }
  1803. /* NET/ROM state change upcall routine */
  1804. static void
  1805. s_nscall(cb,old,new)
  1806. struct nr4cb *cb;
  1807. int old,new;
  1808. {
  1809.     int s,ns;
  1810.     struct usock *up,*nup,*oup;
  1811.     union sp sp;
  1812.  
  1813.     s = cb->user;
  1814.     oup = up = itop(s);
  1815.  
  1816.      if(new == NR4STDISC && up != NULLUSOCK){
  1817.         /* Clean up. If the user has already closed the socket,
  1818.          * then up will be null (s was set to -1 by the close routine).
  1819.          * If not, then this is an abnormal close (e.g., a reset)
  1820.          * and clearing out the pointer in the socket structure will
  1821.          * prevent any further operations on what will be a freed
  1822.          * control block. Also wake up anybody waiting on events
  1823.          * related to this cb so they will notice it disappearing.
  1824.          */
  1825.          up->cb.nr4 = NULLNR4CB;
  1826.          up->errcodes[0] = cb->dreason;
  1827.      }
  1828.      if(new == NR4STCON && old == NR4STDISC){
  1829.         /* Handle an incoming connection. If this is a server cb,
  1830.          * then we're being handed a "clone" cb and we need to
  1831.          * create a new socket structure for it. In either case,
  1832.          * find out who we're talking to and wake up the guy waiting
  1833.          * for the connection.
  1834.          */
  1835.         if(cb->clone){
  1836.             /* Clone the socket */
  1837.             ns = socket(AF_NETROM,SOCK_SEQPACKET,0);
  1838.             nup = itop(ns);
  1839.             ASSIGN(*nup,*up);
  1840.             cb->user = ns;
  1841.             nup->cb.nr4 = cb;
  1842.             cb->clone = 0; /* to avoid getting here again */
  1843.             /* Allocate new memory for the name areas */
  1844.             nup->name = mallocw(sizeof(struct sockaddr_nr));
  1845.             nup->peername = mallocw(sizeof(struct sockaddr_nr));
  1846.             /* Store the new socket # in the old one */
  1847.             up->rdysock = ns;
  1848.             up = nup;
  1849.             s = ns;
  1850.         } else {
  1851.             /* Allocate space for the peer's name */
  1852.             up->peername = mallocw(sizeof(struct sockaddr_nr));
  1853.             /* Store the old socket # in the old socket */
  1854.             up->rdysock = s;
  1855.         }
  1856.         /* Load the addresses. Memory for the name has already
  1857.          * been allocated, either above or in the original bind.
  1858.          */
  1859.         sp.p = up->name;
  1860.         sp.nr->nr_family = AF_NETROM;
  1861.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->local);
  1862.         up->namelen = sizeof(struct sockaddr_nr);
  1863.  
  1864.         sp.p = up->peername;
  1865.         sp.nr->nr_family = AF_NETROM;
  1866.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->remote);
  1867.         up->peernamelen = sizeof(struct sockaddr_nr);
  1868.  
  1869.         /* Wake up the guy accepting it, and let him run */
  1870.         psignal(oup,1);
  1871.         pwait(NULL);
  1872.     }
  1873.      /* Ignore all other state transitions */    
  1874.     psignal(up,0);    /* In case anybody's waiting */
  1875. }
  1876. #endif
  1877.  
  1878. /* Verify address family and length according to the socket type */
  1879. static int
  1880. checkaddr(type,name,namelen)
  1881. int type;
  1882. char *name;
  1883. int namelen;
  1884. {
  1885.     union sp sp;
  1886.  
  1887.     sp.p = name;
  1888.     /* Verify length and address family according to protocol */
  1889.     switch(type){
  1890.     case TYPE_TCP:
  1891.     case TYPE_UDP:
  1892.         if(sp.in->sin_family != AF_INET
  1893.          || namelen != sizeof(struct sockaddr_in))
  1894.             return -1;
  1895.         break;
  1896. #ifdef    AX25
  1897.     case TYPE_AX25I:
  1898.     case TYPE_AX25UI:
  1899.         if(sp.ax->sax_family != AF_AX25
  1900.          || namelen != sizeof(struct sockaddr_ax))
  1901.             return -1;
  1902.         break;
  1903. #endif
  1904. #ifdef    NETROM
  1905.     case TYPE_NETROML3:
  1906.     case TYPE_NETROML4:
  1907.         if(sp.nr->nr_family != AF_NETROM
  1908.          || namelen != sizeof(struct sockaddr_nr))
  1909.             return -1;
  1910.         break;
  1911. #endif
  1912.     }
  1913.     return 0;
  1914. }
  1915. /* Issue an automatic bind of a local address */
  1916. static void
  1917. autobind(s,af)
  1918. int s,af;
  1919. {
  1920.     char buf[MAXSOCKSIZE];
  1921.     union sp sp;
  1922.  
  1923.     sp.p = buf;
  1924.     switch(af){
  1925.     case AF_INET:
  1926.         sp.in->sin_family = AF_INET;
  1927.         sp.in->sin_addr.s_addr = INADDR_ANY;
  1928.         sp.in->sin_port = Lport++;
  1929.         bind(s,sp.p,sizeof(struct sockaddr_in));
  1930.         break;
  1931. #ifdef    AX25
  1932.     case AF_AX25:
  1933.         sp.ax->sax_family = AF_AX25;
  1934.         memset(sp.ax->ax25_addr,'\0',AXALEN);
  1935.         memset(sp.ax->iface,'\0',ILEN);
  1936.         bind(s,sp.p,sizeof(struct sockaddr_ax));
  1937.         break;
  1938. #endif
  1939. #ifdef    NETROM
  1940.     case AF_NETROM:
  1941.         sp.nr->nr_family = AF_NETROM;
  1942.         memcpy(sp.nr->nr_addr.user,Mycall,AXALEN);
  1943.         memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  1944.         bind(s,sp.p,sizeof(struct sockaddr_nr));
  1945.         break;
  1946. #endif
  1947.     }
  1948. }
  1949.  
  1950. /* Return a pair of mutually connected sockets in sv[0] and sv[1] */
  1951. int
  1952. socketpair(af,type,protocol,sv)
  1953. int af;
  1954. int type;
  1955. int protocol;
  1956. int sv[];
  1957. {
  1958.     struct usock *up0, *up1;
  1959.     if(sv == NULLINT){
  1960.         errno = EFAULT;
  1961.         return -1;
  1962.     }
  1963.     if(af != AF_LOCAL){
  1964.         errno = EAFNOSUPPORT;
  1965.         return -1;
  1966.     }
  1967.     if(type != SOCK_STREAM && type != SOCK_DGRAM){
  1968.         errno = ESOCKTNOSUPPORT;
  1969.         return -1;
  1970.     }
  1971.     if((sv[0] = socket(af,type,protocol)) == -1)
  1972.         return -1;
  1973.     if((sv[1] = socket(af,type,protocol)) == -1){
  1974.         close_s(sv[0]);
  1975.         return -1;
  1976.     }
  1977.     up0 = itop(sv[0]);
  1978.     up1 = itop(sv[1]);
  1979.     up0->cb.local->peer = up1;
  1980.     up1->cb.local->peer = up0;
  1981.     return sv[1];
  1982. }
  1983.